<?php
namespace App\Http\Controllers\Api\Cq;

use App\Http\Controllers\Controller;
use App\User;
use App\UserCoinLog;
use App\GameZghpt;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Jobs\SendWechatMessage;

/**
 * 猜拳
 *
 * @author  Kay
 * @version 1.0.0
 */
class CqController extends Controller {

    const bussiness_id  = 4;        // 猜拳
    const threshold_xyb = -1000;    // 止损阀值
    const change_probability = 8;  // 换人概率

    protected $wechat;

    //奖励层级
    private $reward_count = 2;

    //赔率
    protected $config = [
        'peilv' => [
            1 => ['id' => 1, 'name' => '赢', 'rate' => 40],
            2 => ['id' => 2, 'name' => '输', 'rate' => 55],
            3 => ['id' => 3, 'name' => '平', 'rate' => 25],
        ]
    ];

    public function __construct() {
        $this->wechat = app('wechat');
    }

    /**
     * 获取用户个人信息
     *
     * @return [type] [description]
     */
    public function getUserInfo() {
        $id = $this->getLoginUser();
        DB::setFetchMode(\PDO::FETCH_ASSOC);
        $user = DB::table('user')->where('id', $id)->first();
        $user['XYB'] = UserCoinLog::totalXyb($user['id']) * 100;
        $this->echoJson(0, '', $user);
    }

    /**
     * 出拳接口
     *
     * @return [type] [description]
     */
    public function hand(Request $request) {

        $robot_id = $request->input('rid'); /* 当前对战的机器人ID */
        $hand = $request->input('hand');    /* 1-石头，2-剪子，3-布 */
        $gold = $request->input('gold');    /* 100 500 1000 5000 */

        // 检查请求参数
        if (empty($robot_id) || empty($hand) || empty($gold)) {
            return $this->echoJson(1, '请求参数不合法');
        }

        // 检查投注数量
        $gold = intval($gold)/100;
        if ($gold != 1 && $gold != 5 && $gold != 10 && $gold != 50) {
            return $this->echoJson(1, '投注数量不合法');
        }

        // 限定操作频次
        $id = $this->getLoginUser();
        $redis = $this->getRedis();
        $key = "cq:hand:$id";
        if (!$redis->set($key, 'Y', Array('nx', 'px' => 1000))) {
            $this->echoJson(1, '您的操作过于频繁，请稍后再试');
        }

        // 真实用户
        DB::setFetchMode(\PDO::FETCH_ASSOC);
        $user = DB::table('user')->where('id', $id)->first();
        $user['XYB'] = UserCoinLog::totalXyb($user['id']);

        // 机器用户
        $robot = DB::table('robot')->where('robot_id', $robot_id)->first();

        // 按配置概率判定胜负
        $result = $this->get_rand($this->config['peilv']);
        $change = 'N';

        // 机器人小妖币不足，提示平局并且换人
        if ($robot['XYB'] - $gold < 0) {
            $result = 3;
            $change = 'Y';
        }

        // 根据当日盈亏调整概率，亏损超过阀值，则直接判定用户输
        $day_stat_key = sprintf("cq:stat:%s", date('Ymd', time()));
        $profit = $redis->get($day_stat_key);
        if (intval($profit) < self::threshold_xyb) {
            $result = 2;
        }

        switch ($result) {
            case 1:     // 用户赢
                $user_xyb   = $user['XYB'] + $gold;
                $robot_xyb  = $robot['XYB'] - $gold;
                // 判断余额
                if ($robot_xyb < 0) {
                    return $this->echoJson(1, '对方小妖币余额不足！');
                }
                // 更新用户、机器人小妖币
                DB::table('user')->where('id', $user['id'])->update(['XYB' => $user_xyb]);
                DB::table('robot')->where('robot_id', $robot['robot_id'])->update(['XYB' => $robot_xyb]);
                // 记录对局结果
                $data = [
                    'user_id' => $user['id'],
                    'robot_id' => $robot['robot_id'],
                    'bet_result' => $result,
                    'bet_xyb' => $gold,
                    'user_left_xyb' => $user_xyb,
                    'robot_left_xyb' => $robot_xyb,
                ];
                DB::table('game_cq_record_log')->insert($data);
                // 记录真实用户小妖币获取日志
                $key = sprintf("%s-%s-%s-%s", self::bussiness_id, $user['id'], $gold, time());
                UserCoinLog::log(self::bussiness_id, $user['id'], UserCoinLog::TYPE_XYB, $gold, '猜拳赢得小妖币', $key);
                // 换人
                $change = rand(1, 100) < self::change_probability ? 'Y' : 'N';
                // 当日盈亏统计
                $day_stat_key = sprintf("cq:stat:%s", date('Ymd', time()));
                $redis->incrBy($day_stat_key, -$gold);
                $redis->setTimeout($day_stat_key, 7*24*60*60);
                // 奖励上级
                $this->rewardFinder($user, $gold);
                break;
            case 2:     // 用户输
                $user_xyb   = $user['XYB'] - $gold;
                $robot_xyb  = $robot['XYB'] + $gold;
                // 判断余额
                if ($user_xyb < 0) {
                    return $this->echoJson(1, '您的小妖币余额不足！');
                }
                // 更新用户、机器人小妖币
                DB::table('user')->where('id', $user['id'])->update(['XYB' => $user_xyb]);
                DB::table('robot')->where('robot_id', $robot['robot_id'])->update(['XYB' => $robot_xyb]);
                // 记录对局结果
                $data = [
                    'user_id' => $user['id'],
                    'robot_id' => $robot['robot_id'],
                    'bet_result' => $result,
                    'bet_xyb' => $gold,
                    'user_left_xyb' => $user_xyb,
                    'robot_left_xyb' => $robot_xyb,
                ];
                DB::table('game_cq_record_log')->insert($data);
                // 记录真实用户小妖币获取日志
                $key = sprintf("%s-%s-%s-%s", self::bussiness_id, $user['id'], $gold, time());
                UserCoinLog::log(self::bussiness_id, $user['id'], UserCoinLog::TYPE_XYB, -$gold, '猜拳输掉小妖币', $key);
                // 换人
                $change = rand(1, 100) < self::change_probability ? 'Y' : 'N';
                // 当日盈亏统计
                $day_stat_key = sprintf("cq:stat:%s", date('Ymd', time()));
                $redis->incrBy($day_stat_key, $gold);
                $redis->setTimeout($day_stat_key, 7*24*60*60);
                break;
            default:    // 平局
                $user_xyb   = $user['XYB'];
                $robot_xyb  = $robot['XYB'];
                // 记录对局结果
                $data = [
                    'user_id' => $user['id'],
                    'robot_id' => $robot['robot_id'],
                    'bet_result' => $result,
                    'bet_xyb' => $gold,
                    'user_left_xyb' => $user_xyb,
                    'robot_left_xyb' => $robot_xyb,
                ];
                DB::table('game_cq_record_log')->insert($data);
                break;
        }

        $data = [
            'result' => $result,
            'side' => [ 'coin' => $robot_xyb * 100 ],
            'self' => [ 'coin' => $user_xyb * 100 ],
            'change' => $change
        ];

        //取得当前用户是否出现财神到
        $tmp_user_id = $user['id'];
        $user = new \App\Tools\User\User();
        $data['isCaiShen'] = $user->getUserIsCoupon($tmp_user_id);

        $this->echoJson(0, '', $data);
    }

    /**
     * 获取用户个人信息
     *
     * @return [type] [description]
     */
    public function change() {

        // 考虑机器人数据量不多，获取机器人总数
        $robot_count = DB::table('robot')->count();

        // 随机取出一个机器人
        $offset = rand(1, $robot_count) - 1;
        DB::setFetchMode(\PDO::FETCH_ASSOC);
        $robot = DB::table('robot')->offset($offset)->limit(1)->first();

        // 如果机器人小妖币低于阀值，则自动调整机器人小妖币数量
        if ($robot['XYB'] < 62) {
            $robot['XYB'] = rand(8000,67000)/100;
            DB::table('robot')->where('robot_id', $robot['robot_id'])->update(['XYB' => $robot['XYB']]);
        }

        // 返回数据
        $data = [
            'rid' => $robot['robot_id'],
            'nickname' => $robot['nickname'],
            'avatar' => $robot['avatar'],
            'coin' => $robot['XYB'] * 100,
        ];

        $this->echoJson(0, '', $data);
    }

    /**
     * 猜拳概率算法
     *
     * @param  [type] $rand [description]
     * @return [type]       [description]
     */
    private function get_rand($rand) {
        $result = '';
        //概率数组的总概率精度
        $sum = 0;
        foreach ($rand as $v) {
            $sum += $v['rate'] * 100;
        }
        //概率数组循环
        foreach ($rand as $v) {
            $rate = $v['rate'] * 100;
            //抽取随机数
            $rand_num = mt_rand(1, $sum);
            if ($rand_num <= $rate) {
                //得出结果
                $result = $v['id'];
                break;
            } else {
                $sum -= $rate;
            }
        }
        unset ($rand);
        return $result;
    }

    /**
     * 验证登录
     *
     * @return [type] [description]
     */
    private function getLoginUser() {
        // 检查用户登录态
        $user = auth()->user();
        $uid = $user->id;
        return $uid;
    }

    /**
     * 获取Redis实例
     *
     * @return [type] [description]
     */
    private function getRedis() {
        static $redis = null;
        if (empty($redis)) {
            $redis = new \Redis();
            $redis->connect(env('REDIS_HOST'), env('REDIS_PORT'));
            $redis->auth(env('REDIS_PASSWORD'));
        }
        return $redis;
    }

    /**
     * 响应JSON/JSONP格式数据
     *
     * @param  integer $code [返回代码：0 成功 1 失败]
     * @param  string  $msg  [错误信息]
     * @param  array   $data [返回数据]
     * @return [type]        [description]
     */
    private function echoJson($code = 0, $msg = '', $data = []) {
        header('Content-type: application/json');
        $result = [
            'code'  => $code,
            'msg'   => $msg,
            'data'  => $data,
        ];
        $json = json_encode($result);

        // JSONP
        if (!empty($_GET['callback'])) {
            $json = $_GET['callback'] . "(" . $json . ")";
        }
        echo $json;
        exit(0);
    }

    /**
     * 奖励上级
     */
    public function rewardFinder($user, $total)
    {
        if ($this->reward_count) {
            if ($finder = User::where('id', $user['finder_id'])->first()) {
                if (floatval($xyb = bcmul($total, 0.01, 2))) {
                    if(!$gameZghpt = $finder->game_zghpt){
                        $gameZghpt = new GameZghpt();
                        $gameZghpt->user_id = $finder->id;
                        $gameZghpt->quota = 0;
                        $gameZghpt->level = 0;
                        $gameZghpt->save();
                    }
                    if($gameZghpt->level) {
                        $tmp_xyb = $xyb * 100;
                        $message = '恭喜您获得' . $tmp_xyb . '个小妖币的推荐奖励。';

                        $key = '4-'. $finder->id . '-' . $xyb . '-' . time() . '-1';
                        UserCoinLog::log( 4, $finder->id, UserCoinLog::TYPE_XYB, $xyb, '推荐奖励', $key );
                    } else {
                        $message = '您好，您错过了'. $xyb .'小妖币的红包，请<a href="http://ga.cloudxt.cn/zghpt/vip/page">立即升级VIP</a>！';
                    }

                    $this->dispatch(new SendWechatMessage($finder->openid, $message));

                    $this->reward_count--;
                    $this->rewardFinder($finder, $total);
                }
            }
        }
    }

}
